/* for lex */
/* flex -okh_lex.c -Pkhs_ kh_lex.l */

%option yylineno

DIGIT		[0-9]
LETTER		[a-zA-Z\x80-\xFF_]
HEX			[a-fA-F0-9]
BINARY		[0-1]
EXPNT		[Ee][+-]?{DIGIT}+
FLT			(f|F)
INT			(i|I|u|U)*
LONG		[lL]

%{
/*
FLT			(f|F|l|L)
INT			(u|U|l|L)*
*/

#if _MSC_VER
#pragma warning(push)
#pragma warning(disable:4102)
#pragma warning(disable:4127)
#pragma warning(disable:4131)
#pragma warning(disable:4244)
#pragma warning(disable:4267)
#pragma warning(disable:4701)
#pragma warning(disable:4702)
#pragma warning(disable:4996)
#include <stdio.h>
#include <stdarg.h>
#include <memory.h>
#else
#include "stdafx.h"
#endif
#ifdef KAPI
#undef KAPI
#endif
#define SB_INTERNAL	1
#define KAPI extern
#include "sbcs.h"
#include "kh_yacc.h"

#if _SB_WINDOWS_
#define exit			k_exit
#define free			k_free
#define realloc			k_realloc
#define malloc			k_allocf
#endif

static void kh_lex_cmmt(kint t);
static void kh_lex_count(void);
%}

%%

"/%"										{ kh_lex_cmmt('%'); }
"/*"										{ kh_lex_cmmt('*'); }
"//"[^\n]*									{ }

"super"										{ /* reserved */ kh_lex_count(); return KEYWORD_RESERVED; }
"public"									{ kh_lex_count(); return KEYWORD_PUBLIC; }
"local"										{ kh_lex_count(); return KEYWORD_LOCAL; }
"var"										{ kh_lex_count(); return KEYWORD_LOCAL; }
"self"										{ kh_lex_count(); return KEYWORD_SELF; }
"this"										{ kh_lex_count(); return KEYWORD_SELF; }
"if"										{ kh_lex_count(); return KEYWORD_IF; }
"else"										{ kh_lex_count(); return KEYWORD_ELSE; }
"while"										{ kh_lex_count(); return KEYWORD_WHILE; }
"do"										{ kh_lex_count(); return KEYWORD_DO; }
"for"										{ kh_lex_count(); return KEYWORD_FOR; }
"foreach"									{ kh_lex_count(); return KEYWORD_FOREACH; }
"return"									{ kh_lex_count(); return KEYWORD_RETURN; }
"break"										{ kh_lex_count(); return KEYWORD_BREAK; }
"continue"									{ kh_lex_count(); return KEYWORD_CONTINUE; }
"true"										{ kh_lex_count(); return KEYWORD_TRUE; }
"false"										{ kh_lex_count(); return KEYWORD_FALSE; }
"null"										{ kh_lex_count(); return KEYWORD_NULL; }
"function"									{ kh_lex_count(); return KEYWORD_FUNCTION; }
"table"										{ kh_lex_count(); return KEYWORD_TABLE; }
"array"										{ kh_lex_count(); return KEYWORD_ARRAY; }
"in"										{ kh_lex_count(); return KEYWORD_IN; }
"switch"									{ kh_lex_count(); return KEYWORD_SWITCH; }
"case"										{ kh_lex_count(); return KEYWORD_CASE; }
"default"									{ kh_lex_count(); return KEYWORD_DEFAULT; }
"goto"										{ kh_lex_count(); return KEYWORD_GOTO; }
"new"										{ kh_lex_count(); return KEYWORD_NEW; }
"suspend"									{ kh_lex_count(); return KEYWORD_SUSPEND; }
"lock"										{ kh_lex_count(); return KEYWORD_LOCK; }
"__line"									{ kh_lex_count(); return KEYWORD_LINE; }
"__breakpoint"								{ kh_lex_count(); return KEYWORD_BREAKPOINT; }
"__suspend"									{ kh_lex_count(); return KEYWORD_SUSPEND; }
"__lock"									{ kh_lex_count(); return KEYWORD_LOCK; }
"sizeof"									{ kh_lex_count(); return OP_SIZEOF; }
"typename"									{ kh_lex_count(); return OP_TYPENAME; }

{LETTER}({LETTER}|{DIGIT})*					{ kh_lex_count(); return IDENTIFIER; }

0[xX]{HEX}+{INT}?							{ kh_lex_count(); return CONSTANT_INT_HEX; }
0[bB]{BINARY}+{INT}?						{ kh_lex_count(); return CONSTANT_INT_BIN; }
{DIGIT}+{INT}?								{ kh_lex_count(); return CONSTANT_INT; }
0[xX]{HEX}+{INT}?{LONG}						{ kh_lex_count(); return CONSTANT_LONG_HEX; }
0[bB]{BINARY}+{INT}?{LONG}					{ kh_lex_count(); return CONSTANT_LONG_BIN; }
{DIGIT}+{INT}?{LONG}						{ kh_lex_count(); return CONSTANT_LONG; }
{DIGIT}+{EXPNT}{FLT}?						{ kh_lex_count(); return CONSTANT_FLOAT; }
{DIGIT}*"."{DIGIT}+({EXPNT})?{FLT}?			{ kh_lex_count(); return CONSTANT_FLOAT; }
{DIGIT}+"."{DIGIT}*({EXPNT})?{FLT}?			{ kh_lex_count(); return CONSTANT_FLOAT; }
{DIGIT}+{EXPNT}{LONG}{FLT}?					{ kh_lex_count(); return CONSTANT_DOUBLE; }
{DIGIT}*"."{DIGIT}+({EXPNT})?{LONG}{FLT}?	{ kh_lex_count(); return CONSTANT_DOUBLE; }
{DIGIT}+"."{DIGIT}*({EXPNT})?{LONG}{FLT}?	{ kh_lex_count(); return CONSTANT_DOUBLE; }
'(\\.|[^\\'])+'								{ kh_lex_count(); return CONSTANT_CHAR; }
`([^`]|`{2})*`								{ kh_lex_count(); return CONSTANT_STRING; }
\"(\\.|[^\\"])*\"							{ kh_lex_count(); return CONSTANT_STRING; }
@\"(\\.|[^\\"])*\"							{ kh_lex_count(); return CONSTANT_STRING; }
#\"(\\.|[^\\"])*\"							{ kh_lex_count(); return CONSTANT_STRING; }
L'(\\.|[^\\'])+'							{ kh_lex_count(); return CONSTANT_WIDECHAR; }
L\"(\\.|[^\\"])*\"							{ kh_lex_count(); return CONSTANT_WIDESTRING; }

">>="										{ kh_lex_count(); return OP_SHR_ASSIGN; }
"<<="										{ kh_lex_count(); return OP_SHL_ASSIGN; }
"+="										{ kh_lex_count(); return OP_ADD_ASSIGN; }
"-="										{ kh_lex_count(); return OP_SUB_ASSIGN; }
"*="										{ kh_lex_count(); return OP_MUL_ASSIGN; }
"/="										{ kh_lex_count(); return OP_DIV_ASSIGN; }
"%="										{ kh_lex_count(); return OP_MOD_ASSIGN; }
"&="										{ kh_lex_count(); return OP_AND_ASSIGN; }
"^="										{ kh_lex_count(); return OP_XOR_ASSIGN; }
"|="										{ kh_lex_count(); return OP_OR_ASSIGN; }
">>"										{ kh_lex_count(); return OP_SHR; }
"<<"										{ kh_lex_count(); return OP_SHL; }
"++"										{ kh_lex_count(); return OP_INC; }
"--"										{ kh_lex_count(); return OP_DEC; }
"&&"										{ kh_lex_count(); return OP_AND; }
"||"										{ kh_lex_count(); return OP_OR; }
"<="										{ kh_lex_count(); return OP_LTE; }
">="										{ kh_lex_count(); return OP_GTE; }
"=="										{ kh_lex_count(); return OP_EQ; }
"!="										{ kh_lex_count(); return OP_NEQ; }
";"											{ kh_lex_count(); return ';'; }
("{"|"<%")									{ kh_lex_count(); return '{'; }
("}"|"%>")									{ kh_lex_count(); return '}'; }
","											{ kh_lex_count(); return ','; }
":"											{ kh_lex_count(); return ':'; }
"="											{ kh_lex_count(); return '='; }
"("											{ kh_lex_count(); return '('; }
")"											{ kh_lex_count(); return ')'; }
("["|"<:")									{ kh_lex_count(); return '['; }
("]"|":>")									{ kh_lex_count(); return ']'; }
"."											{ kh_lex_count(); return '.'; }
"&"											{ kh_lex_count(); return '&'; }
"!"											{ kh_lex_count(); return '!'; }
"~"											{ kh_lex_count(); return '~'; }
"-"											{ kh_lex_count(); return '-'; }
"+"											{ kh_lex_count(); return '+'; }
"*"											{ kh_lex_count(); return '*'; }
"/"											{ kh_lex_count(); return '/'; }
"%"											{ kh_lex_count(); return '%'; }
"<"											{ kh_lex_count(); return '<'; }
">"											{ kh_lex_count(); return '>'; }
"^"											{ kh_lex_count(); return '^'; }
"|"											{ kh_lex_count(); return '|'; }
"?"											{ kh_lex_count(); return '?'; }
("@"|"->")									{ kh_lex_count(); return OP_PREP; }
"@{"										{ kh_lex_count(); return OP_TABLE; }
"@["										{ kh_lex_count(); return OP_ARRAY; }

[ \t\v\r\n\f]								{ kh_lex_count(); }
.											{ return TOKEN_ERROR; }

%%

/* global */
const kchar* khs_filename = NULL;
kint khs_column = 0;
kint khs_tabsize = 4;
kcham khs_utf8 = FALSE;

/* yywrap */
kint khs_wrap()
{
	return 1;
}

/* comment */
static void kh_lex_cmmt(kint t)
{
	int c;
	while ((c = input()) != 0 && c != EOF)
	{
		if (c == t)
		{
			if ((c = input()) == '/')
				break;
			else
				unput(c);
		}
	}
}

/* count (+column, +tab) */
static void kh_lex_count()
{
	kint i;
	for (i = 0; yytext[i] != '\0'; i++)
	{
		if (yytext[i] == '\n')
			khs_column = 1;
		else if (yytext[i] == '\t')
			khs_column += khs_tabsize - (khs_column % khs_tabsize);
		else
			khs_column++;
	}
			
	/*ECHO;*/
}

#if defined(_MSC_VER)
#pragma warning(pop)
#endif

